/*
 * @(#)ObjectMapperUtils.java 2015-7-9
 *
 * Copyright (c) 2010 by vcread.com. All rights reserved.
 */
package com.nuctech.common.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Map;

import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 基于com.fasterxml.jackson的JSON数据处理工具类
 * 
 * @author lilu
 * @date 2020年4月29日
 * @since 1.0.0
 */
@Slf4j
public class ObjectMapperUtils {
	
	/**
	 * 将对象序列化成json字符串
	 * 
	 * @author lilu
	 * @date 2020年4月29日 下午4:29:08
	 * @since 1.0.0
	 * 
	 * @param value
	 * @return
	 */
	public static String toJSON(Object object) {
		try {
			return getInstance().writeValueAsString(object);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}

	public static String toJSON(Object object, Class<?> serializationView) {
		try {
			return getInstance().writerWithView(serializationView).writeValueAsString(object);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 将对象序列化成JSON byte数组
	 * 
	 * @author lilu
	 * @date 2020年4月29日 下午4:29:57
	 * @since 1.0.0
	 * 
	 * @param object
	 * @return JSON byte数组
	 */
	public static byte[] toJSONAsBytes(Object object) {
		try {
			return getInstance().writeValueAsBytes(object);
		} catch (JsonProcessingException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 将JSON反序列化成对象
	 * 
	 * @author lilu
	 * @date 2020年4月29日 下午4:33:29
	 * @since 1.0.0
	 * 
	 * @param content
	 * @param valueType
	 * @return
	 */
	public static <T> T fromJSON(String content, Class<T> valueType) {
		try {
			return getInstance().readValue(content, valueType);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 将JSON反序列化成对象
	 * 
	 * @author lilu
	 * @date 2020年4月29日 下午4:33:45
	 * @since 1.0.0
	 * 
	 * @param content
	 * @param typeReference
	 *        泛型类型 <code>new TypeReference&lt;People&lt;Chinese&gt;&gt;(){}</code>
	 * @return
	 */
	public static <T> T fromJSON(String content, TypeReference<T> typeReference) {
		try {
			return getInstance().readValue(content, typeReference);
		} catch (IOException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 将JSON byte数组反序列化成对象
	 * 
	 * @author lilu
	 * @date 2020年4月29日 下午4:38:15
	 * @since 1.0.0
	 * 
	 * @param bytes
	 * @param valueType
	 * @return
	 */
	public static <T> T fromJSON(byte[] bytes, Class<T> valueType) {
		try {
			return getInstance().readValue(bytes, valueType);
		} catch (IOException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 将JSON byte数组反序列化成对象
	 * 
	 * @author lilu
	 * @date 2020年4月29日 下午4:38:28
	 * @since 1.0.0
	 * 
	 * @param bytes
	 * @param typeReference
	 *        泛型类型 <code>new TypeReference&lt;People&lt;Chinese&gt;&gt;(){}</code>
	 * @return
	 */
	public static <T> T fromJSON(byte[] bytes, TypeReference<T> typeReference) {
		try {
			return getInstance().readValue(bytes, typeReference);
		} catch (IOException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 将JSON反序列化成对象
	 * 
	 * @author lilu
	 * @date 2020年4月29日 下午4:39:55
	 * @since 1.0.0
	 * 
	 * @param in
	 * @param valueType
	 * @return
	 */
	public static <T> T fromJSON(InputStream in, Class<T> valueType) {
		try {
			return getInstance().readValue(in, valueType);
		} catch (IOException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 将JSON反序列化成对象
	 * 
	 * @author lilu
	 * @date 2020年4月29日 下午4:39:28
	 * @since 1.0.0
	 * 
	 * @param in
	 * @param typeReference
	 *        泛型类型 <code>new TypeReference&lt;People&lt;Chinese&gt;&gt;(){}</code>
	 * @return
	 */
	public static <T> T fromJSON(InputStream in, TypeReference<T> typeReference) {
		try {
			return getInstance().readValue(in, typeReference);
		} catch (IOException e) {
			throw Exceptions.unchecked(e);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> T toList(String json, Class<? extends Collection> collectionType, Class<?> valueType) {
		if (StrUtil.isBlank(json)) {
			try {
				return (T) collectionType.newInstance();
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		try {
			return (T) getInstance().readValue(json, TypeFactory.defaultInstance().constructCollectionType(collectionType, valueType));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> T toMap(String json, Class<? extends Map> mapType, Class<?> keyType, Class<?> valueType) {
		if (StrUtil.isBlank(json)) {
			try {
				return (T) mapType.newInstance();
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		try {
			return (T) getInstance().readValue(json, TypeFactory.defaultInstance().constructMapType(mapType, keyType, valueType));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static <T> T toPojo(Map<String, Object> fromValue, Class<T> toValueType) {
		return getInstance().convertValue(fromValue, toValueType);
	}

	/**
	 * 将JSON字符串转成JsonNode
	 * 
	 * @author lilu
	 * @date 2020年4月29日 下午4:44:17
	 * @since 1.0.0
	 * 
	 * @param json
	 * @return
	 */
	public static JsonNode readTree(String json) {
		try {
			return getInstance().readTree(json);
		} catch (IOException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 将JSON字符串转成JsonNode
	 * 
	 * @author lilu
	 * @date 2020年4月29日 下午4:44:31
	 * @since 1.0.0
	 * 
	 * @param in
	 * @return
	 */
	public static JsonNode readTree(InputStream in) {
		try {
			return getInstance().readTree(in);
		} catch (IOException e) {
			throw Exceptions.unchecked(e);
		}
	}

	public static JsonNode readTree(byte[] content) {
		try {
			return getInstance().readTree(content);
		} catch (IOException e) {
			throw Exceptions.unchecked(e);
		}
	}

	public static JsonNode readTree(JsonParser jsonParser) {
		try {
			return getInstance().readTree(jsonParser);
		} catch (IOException e) {
			throw Exceptions.unchecked(e);
		}
	}

	public static ObjectMapper getInstance() {
		return JacksonHolder.INSTANCE;
	}

	private static class JacksonHolder {
		private static ObjectMapper INSTANCE = Jackson2ObjectMapperBuilder.json().createXmlMapper(false).build();
	}

	/**
	 * 使用alibaba FastJSON格式化JSON
	 * 
	 * @author lilu
	 * @date 2021年1月5日 下午12:41:32
	 * @since 1.0.0
	 * 
	 * @param result
	 * @return
	 */
	public static Object formatJSON(String json) {
		return JSON.toJSONString(JSONObject.parseObject(json), SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, 
	            SerializerFeature.WriteDateUseDateFormat);
	}

}
